﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Simulation
{
	class EventGenerator
	{
		/// <summary>
		/// Generates arrival events until the max number of customers is reached or the max time has passed
		/// </summary>
		/// <param name="meanInterarrivalTime"></param>
		/// <param name="totalCustomers"></param>
		/// <param name="endTime"></param>
		public PriorityQueue<Event> GenerateArrivals(double meanInterarrivalTime, int totalCustomers, int endTime, double stddev)
		{
			int currTime = 0;
			int customerCount = 0;

			PriorityQueue<Event> queue = new PriorityQueue<Event>();

			//if total customers is undefined then generate until time is exceeded
			if(totalCustomers == -1)
				while (currTime <= endTime)
				{
					Event nextEvent = GenerateNextArrival(meanInterarrivalTime, stddev, currTime);
					nextEvent._customerID = customerCount;
					customerCount++;
					currTime = nextEvent._executionTime;
					queue.Enqueue(nextEvent);
				}

			//if end time is undefined then generate until customer count is reached
			else if (endTime == -1)
				while (customerCount < totalCustomers)
				{
					Event nextEvent = GenerateNextArrival(meanInterarrivalTime, stddev, currTime);
					nextEvent._customerID = customerCount;
					customerCount++;
					currTime = nextEvent._executionTime;
					queue.Enqueue(nextEvent);
				}

			//otherwise generate until one of those limits is reached. An exception is thrown if neither is defined lower in the stack
			else
				while (currTime <= endTime)
				{
					Event nextEvent = GenerateNextArrival(meanInterarrivalTime, stddev, currTime);
					nextEvent._customerID = customerCount;
					customerCount++;
					currTime = nextEvent._executionTime;
					queue.Enqueue(nextEvent);
				}

			
			return queue;

		}

		/// <summary>
		/// Returns an arrival event normally distributed around the mean interarrival time (added to the current time)
		/// </summary>
		/// <param name="meanInterarrivalTime"></param>
		/// <param name="stddev"></param>
		/// <param name="currTime"></param>
		/// <returns></returns>
		private Event GenerateNextArrival(double meanInterarrivalTime, double stddev, int currTime)
		{
			
			int arrivalTime = currTime + (int)SimpleRNG.GetNormal(meanInterarrivalTime, stddev);

			return new Event(arrivalTime, EventTypes.Arrival);
		}

	}
}
